home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
- * avra - Assembler for the Atmel AVR microcontroller series
- * Copyright (C) 1998-1999 Jon Anders Haugum
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- *
- * Author of avra can be reached at:
- * email: jonah@omegav.ntnu.no
- * www: http://www.omegav.ntnu.no/~jonah/el/avra.html
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
-
- #include "misc.h"
- #include "avra.h"
-
- #define IS_UNARY(x) ((x == '!') || (x == '-') || (x == '~'))
- #define IS_OPERATOR(x) ((x == '+') || (x == '-') || (x == '*') || (x == '/') || (x == '%') || (x == '<') || (x == '>') || (x == '=') || (x == '!') || (x == '&') || (x == '^') || (x == '|'))
- #define IS_2ND_OPERATOR(x) ((x == '<') || (x == '>') || (x == '=') || (x == '&') || (x == '|'))
-
- enum
- {
- OPERATOR_ERROR = 0,
- OPERATOR_MUL,
- OPERATOR_DIV,
- OPERATOR_MOD,
- OPERATOR_ADD,
- OPERATOR_SUB,
- OPERATOR_SHIFT_LEFT,
- OPERATOR_SHIFT_RIGHT,
- OPERATOR_LESS_THAN,
- OPERATOR_LESS_OR_EQUAL,
- OPERATOR_GREATER_THAN,
- OPERATOR_GREATER_OR_EQUAL,
- OPERATOR_EQUAL,
- OPERATOR_NOT_EQUAL,
- OPERATOR_BITWISE_AND,
- OPERATOR_BITWISE_XOR,
- OPERATOR_BITWISE_OR,
- OPERATOR_LOGICAL_AND,
- OPERATOR_LOGICAL_OR
- };
-
- enum
- {
- FUNCTION_LOW = 0,
- FUNCTION_HIGH,
- FUNCTION_BYTE2,
- FUNCTION_BYTE3,
- FUNCTION_BYTE4,
- FUNCTION_LWRD,
- FUNCTION_HWRD,
- FUNCTION_PAGE,
- FUNCTION_EXP2,
- FUNCTION_LOG2,
- FUNCTION_COUNT
- };
-
- struct element
- {
- struct element *next;
- int data;
- };
-
- char *function_list[] =
- {
- "low(",
- "high(",
- "byte2(",
- "byte3(",
- "byte4(",
- "lwrd(",
- "hwrd(",
- "page(",
- "exp2(",
- "log2("
- };
-
- int get_expr(struct prog_info *pi, char *data, int *value)
- {
- int ok = True, end = False, i, count, first_flag, length, function;
- char unary, *label;
- struct element *element, *first_element = NULL, *temp_element;
- struct element **last_element = &first_element;
-
- for(i = 0, count = 0, first_flag = True, unary = 0; ; i++)
- {
- if(IS_HOR_SPACE(data[i]));
- else if(IS_END(data[i]))
- {
- if((count % 2) != 1)
- print_msg(pi, MSGTYPE_ERROR, "Missing value in expression");
- else
- end = True;
- break;
- }
- else if(first_flag && IS_UNARY(data[i]))
- {
- unary = data[i];
- first_flag = False;
- }
- else if((count % 2) == 1)
- {
- if(!IS_OPERATOR(data[i]))
- {
- print_msg(pi, MSGTYPE_ERROR, "Illegal operator '%c'", data[i]);
- break;
- }
- element = malloc(sizeof(struct element));
- if(!element)
- {
- print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
- ok = False;
- break;
- }
- element->next = NULL;
- element->data = get_operator(&data[i]);
- if(element->data == OPERATOR_ERROR)
- {
- if(IS_2ND_OPERATOR(data[i + 1]))
- print_msg(pi, MSGTYPE_ERROR, "Unknown operator %c%c", data[i], data[i + 1]);
- else
- print_msg(pi, MSGTYPE_ERROR, "Unknown operator %c", data[i]);
- break;
- }
- *last_element = element;
- last_element = &element->next;
- if(IS_2ND_OPERATOR(data[i + 1]))
- i++;
- count++;
- first_flag = True;
- unary = 0;
- }
- else
- {
- element = malloc(sizeof(struct element));
- if(!element)
- {
- print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
- ok = False;
- break;
- }
- element->next = NULL;
- length = 0;
- if(isdigit(data[i]))
- {
- if(tolower(data[i + 1]) == 'x')
- {
- i += 2;
- while(isxdigit(data[i + length])) length++; // TODO: Sjekk overflow
- element->data = atox_n(&data[i], length);
- }
- else if(tolower(data[i + 1]) == 'b')
- {
- i += 2;
- element->data = 0;
- while((data[i + length] == '1') || (data[i + length] == '0'))
- {
- element->data <<= 1;
- element->data |= data[i + length++] - '0'; // TODO: Sjekk overflow
- }
- }
- else
- {
- while(isdigit(data[i + length])) length++;
- element->data = atoi_n(&data[i], length); // TODO: Sjekk overflow
- }
- }
- else if(data[i] == '$')
- {
- i++;
- while(isxdigit(data[i + length])) length++;
- element->data = atox_n(&data[i], length); // TODO: Sjekk overflow
- }
- else if(data[i] == '\'')
- {
- i++;
- element->data = data[i]; // TODO: Sjekk for siste '
- length = 2;
- }
- else if(data[i] == '(')
- {
- i++;
- length = par_length(&data[i]);
- if(length == -1)
- {
- print_msg(pi, MSGTYPE_ERROR, "Missing ')'");
- break;
- }
- data[i + length++] = '\0';
- ok = get_expr(pi, &data[i], &element->data);
- if(!ok)
- break;
- }
- else if(-1 != (function = get_function(&data[i])))
- {
- while(data[i] != '(') i++;
- i++;
- length = par_length(&data[i]);
- if(length == -1)
- {
- print_msg(pi, MSGTYPE_ERROR, "Missing ')'");
- break;
- }
- data[i + length++] = '\0';
- ok = get_expr(pi, &data[i], &element->data);
- if(!ok)
- break;
- element->data = do_function(function, element->data);
- }
- else if(!nocase_strncmp(&data[i], "defined(", 8))
- {
- i += 8;
- length = par_length(&data[i]);
- if(length == -1)
- {
- print_msg(pi, MSGTYPE_ERROR, "Missing ')'");
- break;
- }
- data[i + length++] = '\0';
- if(get_symbol(pi, &data[i], NULL))
- element->data = 1;
- else
- element->data = 0;
- }
- else
- {
- while(IS_LABEL(data[i + length])) length++;
- if((length == 2) && !nocase_strncmp(&data[i], "PC", 2))
- element->data = pi->cseg_addr;
- else
- {
- label = malloc(length + 1);
- if(!label)
- {
- print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
- ok = False;
- break;
- }
- strncpy(label, &data[i], length);
- label[length] = '\0';
- if(get_symbol(pi, label, &element->data))
- free(label);
- else
- {
- print_msg(pi, MSGTYPE_ERROR, "Found no label/variable/constant named %s", label);
- free(label);
- break;
- }
- }
- }
- i += length - 1;
- switch(unary) // TODO: Få den til å takle flere unary på rad.
- {
- case '-':
- element->data = -element->data;
- break;
- case '!':
- element->data = !element->data;
- break;
- case '~':
- element->data = ~element->data;
- }
- *last_element = element;
- last_element = &element->next;
- count++;
- first_flag = False;
- }
- }
- if(end)
- {
- for(i = 13; (i >= 4) && (count != 1); i--)
- {
- for(element = first_element; element->next;)
- {
- if(test_operator_at_precedence(element->next->data, i)) // TODO: Vurder en hi_i for kjapphet
- {
- element->data = calc(pi, element->data, element->next->data, element->next->next->data);
- temp_element = element->next->next->next;
- free(element->next->next);
- free(element->next);
- count -= 2;
- element->next = temp_element;
- }
- else
- element = element->next->next;
- }
- }
- *value = first_element->data;
- }
- for(element = first_element; element;)
- {
- temp_element = element;
- element = element->next;
- free(temp_element);
- }
- return(ok);
- }
-
-
- int get_operator(char *op)
- {
- switch(op[0])
- {
- case '*':
- return(OPERATOR_MUL);
- case '/':
- return(OPERATOR_DIV);
- case '%':
- return(OPERATOR_MOD);
- case '+':
- return(OPERATOR_ADD);
- case '-':
- return(OPERATOR_SUB);
- case '<':
- switch(op[1])
- {
- case '<':
- return(OPERATOR_SHIFT_LEFT);
- case '=':
- return(OPERATOR_LESS_OR_EQUAL);
- default:
- return(OPERATOR_LESS_THAN);
- }
- case '>':
- switch(op[1])
- {
- case '>':
- return(OPERATOR_SHIFT_RIGHT);
- case '=':
- return(OPERATOR_GREATER_OR_EQUAL);
- default:
- return(OPERATOR_GREATER_THAN);
- }
- case '=':
- if(op[1] == '=')
- return(OPERATOR_EQUAL);
- case '!':
- if(op[1] == '=')
- return(OPERATOR_NOT_EQUAL);
- case '&':
- if(op[1] == '&')
- return(OPERATOR_LOGICAL_AND);
- else
- return(OPERATOR_BITWISE_AND);
- case '^':
- return(OPERATOR_BITWISE_XOR);
- case '|':
- if(op[1] == '|')
- return(OPERATOR_LOGICAL_OR);
- else
- return(OPERATOR_BITWISE_OR);
- }
- return(OPERATOR_ERROR);
- }
-
-
- int test_operator_at_precedence(int operator, int precedence)
- {
- switch(precedence)
- {
- case 13:
- return((operator == OPERATOR_MUL) || (operator == OPERATOR_DIV)
- || (operator == OPERATOR_MOD));
- case 12:
- return((operator == OPERATOR_ADD) || (operator == OPERATOR_SUB));
- case 11:
- return((operator == OPERATOR_SHIFT_LEFT) || (operator == OPERATOR_SHIFT_RIGHT));
- case 10:
- return((operator == OPERATOR_LESS_THAN) || (operator == OPERATOR_LESS_OR_EQUAL)
- || (operator == OPERATOR_GREATER_THAN) || (operator == OPERATOR_GREATER_OR_EQUAL));
- case 9:
- return((operator == OPERATOR_EQUAL) || (operator == OPERATOR_NOT_EQUAL));
- case 8:
- return(operator == OPERATOR_BITWISE_AND);
- case 7:
- return(operator == OPERATOR_BITWISE_XOR);
- case 6:
- return(operator == OPERATOR_BITWISE_OR);
- case 5:
- return(operator == OPERATOR_LOGICAL_AND);
- default: /* Makes the compiler shut up */
- case 4:
- return(operator == OPERATOR_LOGICAL_OR);
- }
- }
-
-
- int calc(struct prog_info *pi, int left, int operator, int right) // TODO: Sjekk litt resultater
- {
- switch(operator)
- {
- case OPERATOR_MUL:
- return(left * right);
- case OPERATOR_DIV:
- if(right == 0)
- {
- print_msg(pi, MSGTYPE_ERROR, "Division by zero");
- return(0);
- }
- return(left / right);
- case OPERATOR_MOD:
- if(right == 0)
- {
- print_msg(pi, MSGTYPE_ERROR, "Division by zero (modulus operator)");
- return(0);
- }
- return(left % right);
- case OPERATOR_ADD:
- return(left + right);
- case OPERATOR_SUB:
- return(left - right);
- case OPERATOR_SHIFT_LEFT:
- return(left << right);
- case OPERATOR_SHIFT_RIGHT:
- return(left >> right);
- case OPERATOR_LESS_THAN:
- return(left < right);
- case OPERATOR_LESS_OR_EQUAL:
- return(left <= right);
- case OPERATOR_GREATER_THAN:
- return(left > right);
- case OPERATOR_GREATER_OR_EQUAL:
- return(left >= right);
- case OPERATOR_EQUAL:
- return(left == right);
- case OPERATOR_NOT_EQUAL:
- return(left != right);
- case OPERATOR_BITWISE_AND:
- return(left & right);
- case OPERATOR_BITWISE_XOR:
- return(left ^ right);
- case OPERATOR_BITWISE_OR:
- return(left | right);
- case OPERATOR_LOGICAL_AND:
- return(left && right);
- default: /* Make the compiler shut up */
- case OPERATOR_LOGICAL_OR:
- return(left || right);
- }
- }
-
-
- int get_function(char *function)
- {
- int i;
-
- for(i = 0; i < FUNCTION_COUNT; i++)
- if(!nocase_strncmp(function, function_list[i], strlen(function_list[i]))) return(i);
- return(-1);
- }
-
-
- int do_function(int function, int value)
- {
- switch(function)
- {
- case FUNCTION_LOW:
- return(value & 0xff);
- case FUNCTION_HIGH:
- case FUNCTION_BYTE2:
- return((value >> 8) & 0xff);
- case FUNCTION_BYTE3:
- return((value >> 16) & 0xff);
- case FUNCTION_BYTE4:
- return((value >> 24) & 0xff);
- case FUNCTION_LWRD:
- return(value & 0xffff);
- case FUNCTION_HWRD:
- return((value >> 16) & 0xffff);
- case FUNCTION_PAGE:
- return((value >> 16) & 0xff);
- case FUNCTION_EXP2:
- return(1 << value);
- case FUNCTION_LOG2:
- return(log2(value));
- default:
- return(0);
- }
- }
-
-
- int log2(int value)
- {
- int i = 0;
-
- while(value >>= 1) i++;
- return(i);
- }
-
-
- int get_symbol(struct prog_info *pi, char *label_name, int *data)
- {
- struct label *label;
- struct macro_call *macro_call;
-
- for(label = pi->first_constant; label; label = label->next)
- if(!nocase_strcmp(label->name, label_name))
- {
- if(data)
- *data = label->value;
- return(True);
- }
-
- for(label = pi->first_variable; label; label = label->next)
- if(!nocase_strcmp(label->name, label_name))
- {
- if(data)
- *data = label->value;
- return(True);
- }
-
- for(macro_call = pi->macro_call; macro_call; macro_call = macro_call->prev_on_stack)
- {
- for(label = pi->macro_call->first_label; label; label = label->next)
- if(!nocase_strcmp(label->name, label_name))
- {
- if(data)
- *data = label->value;
- return(True);
- }
- }
-
- for(label = pi->first_label; label; label = label->next)
- if(!nocase_strcmp(label->name, label_name))
- {
- if(data)
- *data = label->value;
- return(True);
- }
-
- return(False);
- }
-
-
- int par_length(char *data)
- {
- int i = 0, b_count = 1;
-
- for(;;)
- {
- if(data[i] == ')')
- {
- b_count--;
- if(!b_count)
- return(i);
- }
- else if(data[i] == '(')
- b_count++;
- else if(data[i] == '\0')
- return(-1);
- i++;
- }
- }
-
-
-
-